//
// Created by HG_Dwx on 2023/12/12.
//
#include "bsp_colorLED.h"
#include "delay.h"


COLOR_RGBC rgb;
COLOR_HSL  hsl;

#define LEDPORT_I2C	    GPIOC			/* GPIO端口 */

#define LEDSCL_PIN		GPIO_PIN_5			/* 连接到SCL时钟线的GPIO */
#define LEDSDA_PIN		GPIO_PIN_4			/* 连接到SDA数据线的GPIO */
#define LEDEN_PIN		GPIO_PIN_3			/* 连接到SDA数据线的GPIO */
/* 定义读写SCL和SDA的宏，已增加代码的可移植性和可阅读性 */
#if 0	/* 条件编译： 1 选择GPIO的库函数实现IO读写 */
#define I2C_SCL_1()  GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN)		/* SCL = 1 */
	#define I2C_SCL_0()  GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN)		/* SCL = 0 */

	#define I2C_SDA_1()  GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN)		/* SDA = 1 */
	#define I2C_SDA_0()  GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN)		/* SDA = 0 */

	#define I2C_SDA_READ()  GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN)	/* 读SDA口线状态 */
#else	/* 这个分支选择直接寄存器操作实现IO读写 */
/*　注意：如下写法，在IAR最高级别优化时，会被编译器错误优化 */
#define LEDSCL_1()  HAL_GPIO_WritePin(LEDPORT_I2C,LEDSCL_PIN,GPIO_PIN_SET)
#define LEDSCL_0()  HAL_GPIO_WritePin(LEDPORT_I2C,LEDSCL_PIN,GPIO_PIN_RESET)			/* SCL = 0 */

#define LEDSDA_1()  HAL_GPIO_WritePin(LEDPORT_I2C,LEDSDA_PIN,GPIO_PIN_SET)
#define LEDSDA_0()  HAL_GPIO_WritePin(LEDPORT_I2C,LEDSDA_PIN,GPIO_PIN_RESET)			/* SCL = 0 */

#define I2C_SDA_READ()  HAL_GPIO_ReadPin(LEDPORT_I2C,LEDSDA_PIN)
#endif

void Delay_s(void)
{
    uint8_t i;
    for (i = 0; i < 10; i++){
        __asm("nop");
    }
}


void TCS34725_I2C_Start(void)
{
    /* 当SCL高电平时，SDA出现一个下跳沿表示I2C总线启动信号 */
    LEDSDA_1();
    LEDSCL_1();
    Delay_s();
    LEDSDA_0();
    Delay_s();
    LEDSCL_0();
    Delay_s();
}

void TCS34725_I2C_Stop()
{
    /* 当SCL高电平时，SDA出现一个上跳沿表示I2C总线停止信号 */
   LEDSDA_0();
   LEDSCL_1();
    Delay_s();
    LEDSDA_1();
}

uint8_t TCS34725_I2C_Wait_ACK()
{
    uint8_t re;

    LEDSDA_1();	/* CPU释放SDA总线 */
    Delay_s();
    LEDSCL_1();	/* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
    Delay_s();
    if (I2C_SDA_READ())	/* CPU读取SDA口线状态 */
    {
        re = 1;
    }
    else
    {
        re = 0;
    }
    LEDSCL_0();
    Delay_s();
    return re;
}

//产生ACK应答
void TCS34725_I2C_ACK()
{
    LEDSDA_0();	/* CPU驱动SDA = 0 */
    Delay_s();
    LEDSCL_1();	/* CPU产生1个时钟 */
    Delay_s();
    LEDSCL_0();
    Delay_s();
    LEDSDA_1();	/* CPU释放SDA总线 */
}

//不产生ACK应答
void TCS34725_I2C_NACK()
{
    LEDSDA_1();	/* CPU驱动SDA = 1 */
    Delay_s();
    LEDSCL_1();	/* CPU产生1个时钟 */
    Delay_s();
    LEDSCL_0();
    Delay_s();
}

//I2C发送一个字节
void TCS34725_I2C_Send_Byte(uint8_t _ucByte)
{
    uint8_t i;

    /* 先发送字节的高位bit7 */
    for (i = 0; i < 8; i++)
    {
        if (_ucByte & 0x80)
        {
            LEDSDA_1();
        }
        else
        {
            LEDSDA_0();
        }
        Delay_s();
        LEDSCL_1();
        Delay_s();
        LEDSCL_0();
        if (i == 7)
        {
            LEDSDA_1(); // 释放总线
        }
        _ucByte <<= 1;	/* 左移一个bit */
        Delay_s();
    }
}

/*********************************************/
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK
uint8_t TCS34725_I2C_Read_Byte(uint8_t ack)
{
    uint8_t i;
    uint8_t value;

    /* 读到第1个bit为数据的bit7 */
    value = 0;
    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        LEDSCL_1();
        Delay_s();
        if (I2C_SDA_READ())
        {
            value++;
        }
        LEDSCL_0();
        Delay_s();
    }
    if(ack==0)
        TCS34725_I2C_NACK();
    else
        TCS34725_I2C_ACK();
    return value;
}


void TCS34725_I2C_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;

            __GPIOC_CLK_ENABLE();

    GPIO_InitStructure.Pin= LEDSCL_PIN|LEDSDA_PIN|LEDEN_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LEDPORT_I2C,&GPIO_InitStructure);
    TCS34725_I2C_Stop();
//    HAL_GPIO_WritePin(LEDPORT_I2C,LEDSCL_PIN,GPIO_PIN_SET);
//    HAL_GPIO_WritePin(LEDPORT_I2C,LEDSDA_PIN,GPIO_PIN_RESET);
//    HAL_GPIO_WritePin(LEDPORT_I2C,LEDEN_PIN,GPIO_PIN_RESET);
}


void TCS34725_I2C_Write(uint8_t slaveAddress, uint8_t* dataBuffer,uint8_t bytesNumber, uint8_t stopBit)
{
    uint8_t i = 0;

    TCS34725_I2C_Start();
    TCS34725_I2C_Send_Byte((slaveAddress << 1) | 0x00);	   //发送从机地址写命令
    TCS34725_I2C_Wait_ACK();
    for(i = 0; i < bytesNumber; i++)
    {
        TCS34725_I2C_Send_Byte(*(dataBuffer + i));
        TCS34725_I2C_Wait_ACK();
    }
    if(stopBit == 1) TCS34725_I2C_Stop();
}

/*******************************************************************************
 * @brief Reads data from a slave device.
 *
 * @param slaveAddress - Adress of the slave device.
 * @param dataBuffer - Pointer to a buffer that will store the received data.
 * @param bytesNumber - Number of bytes to read.
 * @param stopBit - Stop condition control.
 *                  Example: 0 - A stop condition will not be sent;
 *                           1 - A stop condition will be sent.
*******************************************************************************/
void TCS34725_I2C_Read(uint8_t slaveAddress, uint8_t* dataBuffer, uint8_t bytesNumber, uint8_t stopBit)
{
    uint8_t i = 0;

    TCS34725_I2C_Start();
    TCS34725_I2C_Send_Byte((slaveAddress << 1) | 0x01);	   //发送从机地址读命令
    TCS34725_I2C_Wait_ACK();
    for(i = 0; i < bytesNumber; i++)
    {
        if(i == bytesNumber - 1)
        {
            *(dataBuffer + i) = TCS34725_I2C_Read_Byte(0);//读取的最后一个字节发送NACK
        }
        else
        {
            *(dataBuffer + i) = TCS34725_I2C_Read_Byte(1);
        }
    }
    if(stopBit == 1) TCS34725_I2C_Stop();
}
/*******************************************************************************
 * @brief Writes data into TCS34725 registers, starting from the selected
 *        register address pointer.
 *
 * @param subAddr - The selected register address pointer.
 * @param dataBuffer - Pointer to a buffer storing the transmission data.
 * @param bytesNumber - Number of bytes that will be sent.
 *
 * @return None.
*******************************************************************************/
void TCS34725_Write(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
    uint8_t sendBuffer[10] = {0, };
    uint8_t byte = 0;

    sendBuffer[0] = subAddr | TCS34725_COMMAND_BIT;
    for(byte = 1; byte <= bytesNumber; byte++)
    {
        sendBuffer[byte] = dataBuffer[byte - 1];
    }
    TCS34725_I2C_Write(TCS34725_ADDRESS, sendBuffer, bytesNumber + 1, 1);
}
/*******************************************************************************
 * @brief Reads data from TCS34725 registers, starting from the selected
 *        register address pointer.
 *
 * @param subAddr - The selected register address pointer.
 * @param dataBuffer - Pointer to a buffer that will store the received data.
 * @param bytesNumber - Number of bytes that will be read.
 *
 * @return None.
*******************************************************************************/
void TCS34725_Read(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
    subAddr |= TCS34725_COMMAND_BIT;

    TCS34725_I2C_Write(TCS34725_ADDRESS, (uint8_t *)&subAddr, 1, 0);
    TCS34725_I2C_Read(TCS34725_ADDRESS, dataBuffer, bytesNumber, 1);
}
/*******************************************************************************
 * @brief TCS34725设置积分时间
 *
 * @return None
*******************************************************************************/
void TCS34725_SetIntegrationTime(uint8_t time)
{
    TCS34725_Write(TCS34725_ATIME, &time, 1);
}
/*******************************************************************************
 * @brief TCS34725设置增益
 *
 * @return None
*******************************************************************************/
void TCS34725_SetGain(uint8_t gain)
{
    TCS34725_Write(TCS34725_CONTROL, &gain, 1);
}
/*******************************************************************************
 * @brief TCS34725使能
 *
 * @return None
*******************************************************************************/
void TCS34725_Enable(void)
{
    uint8_t cmd = TCS34725_ENABLE_PON;

    TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
    cmd = TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN;
    TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
    //delay_s(600000);//delay_ms(3);//延时应该放在设置AEN之后
}
/*******************************************************************************
 * @brief TCS34725失能
 *
 * @return None
*******************************************************************************/
void TCS34725_Disable(void)
{
    uint8_t cmd = 0;

    TCS34725_Read(TCS34725_ENABLE, &cmd, 1);
    cmd = cmd & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
    TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
}
/*******************************************************************************
 * @brief TCS34725初始化
 *
 * @return ID - ID寄存器中的值
*******************************************************************************/
uint8_t TCS34725_Init(void)
{
    uint8_t id=0;

    TCS34725_I2C_Init();
    TCS34725_Read(TCS34725_ID, &id, 1);  //TCS34725 的 ID 是 0x44 可以根据这个来判断是否成功连接,0x4D是TCS34727;
    printf("id:%02X\n",id);
    if(id==0x4D | id==0x44)
    {
        TCS34725_SetIntegrationTime(TCS34725_INTEGRATIONTIME_2_4MS);
        TCS34725_SetGain(TCS34725_GAIN_1X);
        TCS34725_Enable();
        return 1;
    }
    return 0;
}
/*******************************************************************************
 * @brief TCS34725获取单个通道数据
 *
 * @return data - 该通道的转换值
*******************************************************************************/
uint8_t TCS34725_GetChannelData(uint8_t reg)
{
    uint8_t tmp[2] = {0,0};
    uint16_t data;

    TCS34725_Read(reg, tmp, 2);
    data = (tmp[1] << 8) | tmp[0];

    return data;
}
/*******************************************************************************
 * @brief TCS34725获取各个通道数据
 *
 * @return 1 - 转换完成，数据可用
 *   	   0 - 转换未完成，数据不可用
*******************************************************************************/
uint8_t TCS34725_GetRawData(COLOR_RGBC *rgbc)
{
    uint8_t status = TCS34725_STATUS_AVALID;

    TCS34725_Read(TCS34725_STATUS, &status, 1);

    if(status & TCS34725_STATUS_AVALID)
    {
        rgbc->c = TCS34725_GetChannelData(TCS34725_CDATAL);
        rgbc->r = TCS34725_GetChannelData(TCS34725_RDATAL);
        rgbc->g = TCS34725_GetChannelData(TCS34725_GDATAL);
        rgbc->b = TCS34725_GetChannelData(TCS34725_BDATAL);
        return 1;
    }
    return 0;
}
/******************************************************************************/
//RGB转HSL
void RGBtoHSL(COLOR_RGBC *Rgb, COLOR_HSL *Hsl)
{
    uint8_t maxVal,minVal,difVal;
    uint8_t r = Rgb->r*100/Rgb->c;   //[0-100]
    uint8_t g = Rgb->g*100/Rgb->c;
    uint8_t b = Rgb->b*100/Rgb->c;

    maxVal = max3v(r,g,b);
    minVal = min3v(r,g,b);
    difVal = maxVal-minVal;

    //计算亮度
    Hsl->l = (maxVal+minVal)/2;   //[0-100]

    if(maxVal == minVal)//若r=g=b,灰度
    {
        Hsl->h = 0;
        Hsl->s = 0;
    }
    else
    {
        //计算色调
        if(maxVal==r)
        {
            if(g>=b)
                Hsl->h = 60*(g-b)/difVal;
            else
                Hsl->h = 60*(g-b)/difVal+360;
        }
        else
        {
            if(maxVal==g)Hsl->h = 60*(b-r)/difVal+120;
            else
            if(maxVal==b)Hsl->h = 60*(r-g)/difVal+240;
        }

        //计算饱和度
        if(Hsl->l<=50)Hsl->s=difVal*100/(maxVal+minVal);  //[0-100]
        else
            Hsl->s=difVal*100/(200-(maxVal+minVal));
    }
}
/******************************************************************************/


